package com.myt.matp.gui;

import com.myt.matp.core.EventListener;
import com.myt.matp.core.Event;

import javax.microedition.lcdui.Graphics;
import java.lang.Math;


public abstract class UIWidget implements EventListener {

    // Types
    public static final int UNKNOW = 0;
    public static final int PANEL = 1;
    public static final int EDIT = 2;
    public static final int TEXT = 3;
    public static final int LIST = 4;
    public static final int MULTIOPT = 5;
    public static final int MENU = 6;
    public static final int BANNER = 7;
    public static final int PROMPT = 8;
    public static final int TITLE = 9;
    public static final int LABEL = 10;
    public static final int NUMERIC = 11;
    public static final int NUMSP = 12;
    public static final int DECIMAL = 13;
    public static final int PERCENT = 14;
    public static final int IPADDR = 15;
    public static final int REAL = 16;
    public static final int TIME = 17;
    public static final int DATE = 18;
    public static final int DAY = 19;
    public static final int COMBO = 20;
    public static final int CHECKBOX = 21;
    public static final int RADIOGROUP = 22;
    public static final int BUTTON = 23;
    public static final int SOFT = 24;
    public static final int SCROLLBAR = 25;
    public static final int IMAGE = 26;
    public static final int COLUMN = 27;
    public static final int ROW= 28;
    public static final int ITEM= 29;

    // Color
    public static final int COLOR_BACKGROUND = 0;
    public static final int COLOR_FOREGROUND = 1;
    public static final int COLOR_BORDER = 2;
    public static final int COLOR_CURSOR = 3;

    // PROPERTIES
    public static final int PROP_ACTIVE  = 0x00000001;
    public static final int PROP_VISIBLE = 0x00000002;
    public static final int PROP_3D = 0x00000004;
    public static final int PROP_ROUND = 0x00000008;
    //public static final int PROP_SCROLL = 0x00000010;

    // Constructor
    protected int m_Id = 0;
    protected GUI m_Gui = null;

    // Position and dimension
    private int m_CX = 0;
    private int m_CY = 0;
    private int m_DX = 0;
    private int m_DY = 0;

    // Aspect
    private int m_Border = 1;
    private int m_Margin = 1;

    private int m_ColorBackground = 0xFFFFFF;
    private int m_ColorForeground = 0;
    private int m_ColorBorder = 0;
    private int m_ColorCursor = 0x0000FF;

    // Common properties
    private int m_Properties = PROP_ACTIVE | PROP_VISIBLE;

    // Owned Flags
    protected int m_Flags = 0;

    // Control
    protected boolean m_OnFocus = false;
    private boolean m_Repaint = false;

    protected UIWidget(int id, GUI gui) {
	m_Id = id;
	m_Gui = gui;
	// Default properties
	setProperties(PROP_ACTIVE | PROP_VISIBLE);
    }

    /*
     * Identification
     *
     */

    public final void setId(int id) {
        m_Id = id;
    }

    public final int getId() {
        return m_Id;
    }

    public int getType() {
	return UIWidget.UNKNOW;
    }

    /*
     * Behaviour and aspect commons
     *
     */

    public void setProperties(int properties) {
	m_Properties = m_Properties | properties;
    }

    public void unsetProperties(int properties) {
	properties = ~properties;
	m_Properties = m_Properties & properties;
    }

    public final boolean hasProperties(int properties) {
	return ((m_Properties & properties) > 0);
    }

    public final int getBorder() {
	return m_Border;
    }

    public final void setBorder(int d) {
	m_Border = d;
    }

    public final int getMargin() {
	return m_Margin;
    }

    public final void setMargin(int d) {
	m_Margin = d;
    }

    public final void setColor(int color, int rgb) {
	switch (color) {
	case COLOR_BACKGROUND:
	    m_ColorBackground = rgb;
	    break;
	case COLOR_FOREGROUND:
	    m_ColorForeground = rgb;
	    break;
	case COLOR_BORDER:
	    m_ColorBorder = rgb;
	    break;
	case COLOR_CURSOR:
	    m_ColorCursor = rgb;
	    break;
	}
    }

    public int getColor(int color) {
	int ret = 0;
	switch (color) {
	case COLOR_BACKGROUND:
	    ret = m_ColorBackground;
	    break;
	case COLOR_FOREGROUND:
	    ret = m_ColorForeground;
	    break;
	case COLOR_BORDER:
	    ret = m_ColorBorder;
	    break;
	case COLOR_CURSOR:
	    ret = m_ColorCursor;
	    break;
	}

	return ret;
    }

    /*
     * Sizing and Position
     *
     */

    protected int getMinWidth() {
	return (2 * getBorder() + 2 * getMargin());
    }

    protected int getMinHeight() {
	return (2 * getBorder() + 2 * getMargin());
    }

    protected int getMaxHeight() {
	return GUI.MAX_SIZE;
    }

    protected int getMaxWidth() {
	return GUI.MAX_SIZE;	
    }

    protected final void setArea(int w, int h) {

	int minW = getMinWidth();
	int minH = getMinHeight();
	int maxW = getMaxWidth();
	int maxH = getMaxHeight();

	m_DX = ((w >= minW) && (w <= maxW)) ? w : minW;
	m_DY = ((h >= minH) && (h <= maxH)) ? h : minH;
    }

    protected final void resize(int w, int h) {
	setArea(w, h);
	resized();
    }

    public final int getPosX() {
	return m_CX;
    }

    public final int getPosY() {
	return m_CY;
    }

    public final void setPosX(int x) {
	m_CX = x;
    }

    public final void setPosY(int y) {
	m_CY = y;
    }

    public final int getWidth() {
	return m_DX;
    }

    public final int getHeight() {
	return m_DY;
    }

    protected int getViewX() {
	return getPosX() + getBorder() + getMargin();
    }

    protected int getViewY() {
	return getPosY() + getBorder() + getMargin();
    }

    protected int getViewWidth() {
	return getWidth() - 2 * getBorder() - 2 * getMargin();
    }

    protected int getViewHeight() {
	return getHeight() - 2 * getBorder() - 2 * getMargin();
    }

    /*
     * Control
     *
     */

    public final boolean setFocus() {
	changeFocus(true);
	return isFocused();
    }

    public final void unsetFocus() {
	changeFocus(false);
    }

    protected void changeFocus(boolean value) {
	m_OnFocus = value;
    }

    public final boolean isFocused() {
	return m_OnFocus;
    }

    protected void setRepaint(boolean repaint) {
	m_Repaint = repaint;
    }        

    /*
     * Popup
     *
     */
    
    public final void setPopUp(UIWidget uiw) {
	m_Gui.setPopUp(uiw);
    }

    public final UIWidget getPopUp() {
	return m_Gui.getPopUp();
    }

    /*
     * Events
     *
     */

    public final void postEvent(int id, int wParam, long dwParam, Object obj) {
	m_Gui.postEvent(id, wParam, dwParam, obj);
    }

    public final void postEvent(int id, int wParam, long dwParam) {
	postEvent(id, wParam, dwParam, this);
    }

    public final void postEvent(int id, int wParam) {
	postEvent(id, wParam, 0);
    }

    public final void postEvent(int id) {
	postEvent(id, 0);
    }

    public boolean dispatchEvent(final Event e) {
	return false;
    }

    /*
     * Behaviour and aspect particular
     *
     */ 

    public final void setFlags(int flags) {
	m_Flags = flags;
    }

    public final int getFlags() {
	return m_Flags;
    }

    public final boolean hasFlags(int flags) {
	return ((m_Flags & flags) > 0);
    }
        
    /*
     * Paint
     *
     */
    public final void redraw(int x, int y, int w, int h) {
	if (m_Repaint) {
	    m_Gui.repaint(x, y, w, h);
	}
    }

    public final void redraw() {
	redraw(getPosX(), getPosY(), getWidth(), getHeight());
    }

    protected final void paint(MGraphics g) {

 	//#ifdef DEBUG_UIWIDGET
	//# System.out.println(getClass().getName() + ".paint() {");
	//#endif

	// Cliping
	g.setClip(getPosX(),
		  getPosY(), 
		  getWidth(), 
		  getHeight());

	// Paint background
	paintBackground(g);

	// Paint border
	paintBorder(g);

	// Paint Width
	paintUIWidget(g);

 	//#ifdef DEBUG_UIWIDGET
	//# System.out.println("}");
	//#endif
    }

    protected final void paintBackground(MGraphics g) {
	// Set color
        g.setColor(getColor(COLOR_BACKGROUND));
	// Fill background
        g.fillRect(getPosX(),
		   getPosY(), 
		   getWidth(), 
		   getHeight());
    }

    protected final void paintBorder(MGraphics g) {
	// If has border
	if (getBorder() > 0) {
	    // Set color
	    g.setColor(getColor(COLOR_BORDER));
	    // Set Stroke style
	    g.setStrokeStyle(Graphics.SOLID);
	    // Set brush
	    for (int i = 0; i < getBorder(); i++) {
		g.drawRect(getPosX() + i, 
			   getPosY() + i,
			   getWidth() - 1 - 2 * i,
			   getHeight() - 1 - 2 * i);
	    }
	}
    }


    protected final void initAlarm(long period) {
	m_Gui.initAlarm(hashCode(), period, this);
    }

    protected final void killAlarm() {
	m_Gui.killAlarm(hashCode());
    }

    protected abstract void paintUIWidget(MGraphics g);

    protected abstract void resized();
}
